package com.core.sgip.server;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;

import org.apache.log4j.Logger;

import com.core.sgip.common.SGIPConstant;
import com.core.sgip.common.SGIPMsg;
import com.core.sgip.common.SGIPproperties;
import com.core.sgip.common.body.command.Report;
import com.core.sgip.common.factory.SGIPFactory;
import com.core.sgip.common.head.SGIPMsgHead;
import com.core.sgip.interf.SGIPmessageHandler;
/**
 * 接收客户发送过来的请求
 * 服务
 * @author Guoxing
 *
 */
public class SGIPReceiveServer {

	private static Logger logger = Logger.getLogger(SGIPReceiveServer.class);

	private SGIPmessageHandler sGIPmessageHandler = SGIPproperties.SGIP_MSG_HANDLER;

	private static SGIPReceiveServer instance = new SGIPReceiveServer();

	public static SGIPReceiveServer getInstance() {
		return instance;
	}

	
	public void startSGIPService() {
		try {
			@SuppressWarnings("resource")
			ServerSocket server = new ServerSocket();
			server.bind(new InetSocketAddress(SGIPproperties.LOCALHOST_REQUEST_SERVER_IP,
					SGIPproperties.LOCALHOST_REQUEST_SERVER_PORT));
			logger.info("SGIPReceiveServer service <" + server.getInetAddress() + ":" + server.getLocalPort()
					+ "> 运行中...");
			while (true) {
				Socket socket = server.accept();
				logger.info("监听到" + socket.getInetAddress() + ":" + socket.getLocalPort() + "~~");
				new Thread(new ConnectHandler(socket, sGIPmessageHandler)).start();
			}
		} catch (IOException e) {
			logger.debug("startSGIPReceiveRequestServer 运行异常.详情:" + e);
			e.printStackTrace();
		}
	}

	public void startNIOSGIPService() {
		Selector selector = null;
		ServerSocketChannel serverSocketChannel = null;
		try {
			logger.debug("*********startNIOSGIPService ");
			selector = Selector.open();
			serverSocketChannel = ServerSocketChannel.open();
			serverSocketChannel.configureBlocking(false);
			serverSocketChannel.socket().setReuseAddress(true);
			serverSocketChannel.socket().bind(new InetSocketAddress(8801));
			// serverSocketChannel.socket().bind(
			// new InetSocketAddress(SGIPproperties.LOCALHOST_SGIP_PORT));

			serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
			while (true) {
				if (selector.select() == 0) {
					continue;
				}
				Iterator<SelectionKey> iter = selector.selectedKeys().iterator();
				while (iter.hasNext()) {
					SelectionKey key = (SelectionKey) iter.next();
					iter.remove();
					this.handleKey(key);
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private void handleKey(SelectionKey key) throws IOException {
		if (key.isAcceptable()) {
			// 得到与客户端的套接字通道
			SocketChannel channel = ((ServerSocketChannel) key.channel()).accept();
			channel.configureBlocking(false);
			channel.register(key.selector(), SelectionKey.OP_READ);
		}
		if (key.isReadable()) {
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			SocketChannel socketChannel = (SocketChannel) key.channel();
			socketChannel.configureBlocking(false);
			ByteBuffer buffer = ByteBuffer.allocate(1024);
			try {
				byte[] bytes;
				int size = 0;
				while ((size = socketChannel.read(buffer)) >= 0) {
					buffer.flip();
					bytes = new byte[size];
					buffer.get(bytes);
					baos.write(bytes);
					buffer.clear();
				}
				bytes = baos.toByteArray();

				SGIPMsg sgipMsg = SGIPFactory.constructSGIPMsg(bytes);
				logger.debug("receive sgipMsg:" + sgipMsg);
				SGIPMsgHead head = sgipMsg.getHead();
				if (null != head) {
					long commandId = head.getCommandId();
					if (SGIPConstant.SGIP_BIND == commandId) {
						logger.debug("******************* receive bind *******************");
						key.attach(SGIPConstant.SGIP_BIND_RESP);
					} else if (SGIPConstant.SGIP_DELIVER == commandId) {
						logger.debug("******************* receive deliver *******************");
//						sGIPmessageHandler.handleDeliverMessage(head, (Deliver) sgipMsg.getCommand(),null,null);
						
						
						
						
						
						
						
						
						
						key.attach(SGIPConstant.SGIP_DELIVER_RESP);
					} else if (SGIPConstant.SGIP_REPORT == commandId) {
						logger.debug("******************* receive report *******************");
						sGIPmessageHandler.handleReportMessage(head, (Report) sgipMsg.getCommand());
						key.attach(SGIPConstant.SGIP_REPORT_RESP);
					} else if (SGIPConstant.SGIP_UNBIND == commandId) {
						logger.debug("******************* receive unbind *******************");
						key.attach(SGIPConstant.SGIP_UNBIND_RESP);
					}
				}
			} catch (Exception e) {
				e.printStackTrace();
			} finally {
				baos.close();
				if (buffer != null) {
					buffer = null;
				}
			}
			key.interestOps(SelectionKey.OP_WRITE);
		}
		if (key.isWritable()) {
			boolean isClose = false;
			SocketChannel channel = (SocketChannel) key.channel();
			channel.configureBlocking(false);
			SGIPMsg sgipMsg = null;
			try {
				long sendCommandId = (Long) key.attachment();
				if (SGIPConstant.SGIP_BIND_RESP == sendCommandId) {
					sgipMsg = SGIPFactory.getSGIPMsg(SGIPConstant.SGIP_BIND_RESP);
					logger.debug("******************* send bind resp *******************sgipMsg=" + sgipMsg);
					ByteBuffer block = ByteBuffer.wrap(sgipMsg.getByteData());
					channel.write(block);
				} else if (SGIPConstant.SGIP_DELIVER_RESP == sendCommandId) {
					sgipMsg = SGIPFactory.getSGIPMsg(SGIPConstant.SGIP_DELIVER_RESP);
					logger.debug("******************* send deliver resp *******************sgipMsg=" + sgipMsg);
					ByteBuffer block = ByteBuffer.wrap(sgipMsg.getByteData());
					channel.write(block);
				} else if (SGIPConstant.SGIP_REPORT_RESP == sendCommandId) {
					sgipMsg = SGIPFactory.getSGIPMsg(SGIPConstant.SGIP_REPORT_RESP);
					logger.debug("******************* send report resp *******************sgipMsg=" + sgipMsg);
					ByteBuffer block = ByteBuffer.wrap(sgipMsg.getByteData());
					channel.write(block);
				} else if (SGIPConstant.SGIP_UNBIND_RESP == sendCommandId) {
					sgipMsg = SGIPFactory.getSGIPMsg(SGIPConstant.SGIP_UNBIND_RESP);
					logger.debug("******************* send unbind resp *******************sgipMsg=" + sgipMsg);
					ByteBuffer block = ByteBuffer.wrap(sgipMsg.getByteData());
					channel.write(block);
					isClose = true;
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
			if (isClose) {
				channel.close();
				return;
			} else {
				key.interestOps(SelectionKey.OP_READ);
			}
		}
	}

}
